package com.finalist.captcha.store;

import java.util.Collection;
import java.util.Locale;

import javax.annotation.Resource;

import net.sf.ehcache.CacheException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import com.finalist.captcha.service.CaptchaCacheService;
import com.octo.captcha.Captcha;
import com.octo.captcha.image.ImageCaptcha;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.captchastore.CaptchaAndLocale;
import com.octo.captcha.service.captchastore.CaptchaStore;

@Component("memcacheCaptchaStore")
public class MemcacheCaptchaStore implements CaptchaStore {

	private static Log log = LogFactory.getLog(MemcacheCaptchaStore.class);
	
	@Resource(name = "captchaCacheService")
	private CaptchaCacheService cacheService;

	/**
	 * Check if a captcha is stored for this id
	 * @return true if a captcha for this id is stored, false otherwise
	 */
	public boolean hasCaptcha(String id) {
		try {
			return cacheService.getCaptcha(id) != null;
		} catch (CacheException e) {
			log.error(e);
			return false;
		}
	}

	/**
	 * Store the captcha with the provided id as key. The key is assumed to be
	 * unique, so if the same key is used twice to store a captcha, the store
	 * will return an exception
	 * 
	 * @param id the key
	 * @param captcha  the captcha
	 * @throws com.octo.captcha.service.CaptchaServiceException
	 *         if the captcha already exists, or if an error occurs during  storing routine.
	 */
	public void storeCaptcha(String id, Captcha captcha)
			throws CaptchaServiceException {
		setCaptchaHandled(captcha);
		cacheService.storeCaptcha(id, new CaptchaAndLocale(captcha));
	}
	
	private void setCaptchaHandled(Captcha captcha) {
		try {
			ImageCaptcha ic = (ImageCaptcha) captcha;
			ic.getImageChallenge();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Store the captcha with the provided id as key. The key is assumed to be
	 * unique, so if the same key is used twice to store a captcha, the store
	 * will return an exception
	 * 
	 * @param id the key
	 * @param captcha the captcha
	 * @param locale the locale used that triggers the captcha generation
	 * @throws com.octo.captcha.service.CaptchaServiceException
	 *      if the captcha already exists, or if an error occurs during storing routine.
	 */
	public void storeCaptcha(String id, Captcha captcha, Locale locale)
			throws CaptchaServiceException {
		setCaptchaHandled(captcha);
		cacheService.storeCaptcha(id, new CaptchaAndLocale(captcha, locale));
	}

	/**
	 * Retrieve the captcha for this key from the store.
	 * @return the captcha for this id
	 * @throws CaptchaServiceException if an error occurs during retrieving routine.
	 */
	public Captcha getCaptcha(String id) throws CaptchaServiceException {
		try {
			CaptchaAndLocale t = cacheService.getCaptcha(id);
			if(t != null) {
				return t.getCaptcha();
			}
		} catch (CacheException e) {
			log.error(e);
		}
		return null;
	}

	/**
	 * Retrieve the locale for this key from the store.
	 * @return the locale for this id, null if not found
	 * @throws com.octo.captcha.service.CaptchaServiceException if an error occurs during retrieving routine.
	 */
	public Locale getLocale(String id) throws CaptchaServiceException {
		CaptchaAndLocale captchaAndLocale = cacheService.getCaptcha(id);
	     return captchaAndLocale !=null ? captchaAndLocale.getLocale() : null;
	}

	/**
	 * Remove the captcha with the provided id as key.
	 * @param id the key
	 * @return true if found, false otherwise
	 * @throws CaptchaServiceException  if an error occurs during remove routine
	 */
	public boolean removeCaptcha(String id) {
		cacheService.removeCaptcha(id);
		return true;
	}

	/**
	 * get the size of this store
	 */
	public int getSize() {
		return 1000;

	}

	/**
	 * Return all the contained keys
	 */
	public Collection<?> getKeys() {
		return null;
	}

	/**
	 * Empty the store
	 */
	public void empty() {
		
	}

	@Override
	public void cleanAndShutdown() {
		
	}

	@Override
	public void initAndStart() {

	}
	
}
